#include "main.h"

//LED
uchar led_code = 0;

//SEG
uchar seg_pos = 0;
uchar seg_str[10];
uchar seg_buf[8] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
uchar seg_mode = 0;
uchar seg_mode_old;

//KEY
uchar key_old;

//TIMER
ulong t1_count = 0;
uchar warn_count = 0;

//1302 18b02
uchar RTC[] = {13,25,30};
uint temp = 0;
uint temp_avg = 0;
uint temp_max = 0;
uint temp_old = 0;

//湿度
uint freq = 0;
uint humi = 0;
uint humi_avg = 0;
uint humi_max = 0;
uint humi_old = 0;

//回显
uchar redsp_mode = 0;
ulong pick_time = 0;
uchar pick_num = 0;
uchar pick_RTC[] = {21,13};

//参数
uchar ctrl_temp = 30;
uchar adc_val = 100;

//标志位
bit pick_ed;
bit pick_incre;
bit warn_en;
bit humi_ok = 1;


//===========CLEAR=============
void clear_data() {
	//温度
	temp_avg = 0;
	temp_max = 0;
	//湿度
	humi_avg = 0;
	humi_max = 0;
	//回显
	pick_num = 0;
	pick_RTC[0] = 0;
	pick_RTC[1] = 0;
}


//===========WATER=============
void humi_read() {
	if(freq > 200 && freq < 2000) {
		humi_ok = 1;
		//采集湿度：y=(2*x+50)/45
		humi = ((2*freq+50)/45.0)*10;
	} else {
		humi_ok = 0;
	}
}


//===========CALC=============
void calc_proc() {
	//对比前一次采集
	if((pick_num >= 2) && (temp > temp_old) && (humi > humi_old)) {
		pick_incre = 1;
		temp_old = temp;
		humi_old = humi;
	} else {
		pick_incre = 0;
	}
	
	//计算温度参数
	temp_avg = (temp_avg * (pick_num - 1) + temp) / pick_num;
	if(temp > temp_max)
		temp_max = temp;
	
	//计算湿度参数
	humi_avg = (humi_avg * (pick_num - 1) + humi) / pick_num;
	if(humi > humi_max)
		humi_max = humi;
	
	//记录时间
	pick_RTC[0] = RTC[0];
	pick_RTC[1] = RTC[1];
}


//===========TASK=============
void task_proc() {
	//采集光强
	adc_val = ADC_read(1);
	
	//采集后，3s内不可采集
	if(pick_ed && (t1_count-pick_time) < 3000) return;
	else if(pick_ed) {
		//恢复采集
		if(adc_val > 30)
			pick_ed = 0;
		//切换回原状态
		seg_mode = seg_mode_old;
		return;
	}
	

	
	//触发采集：挡光+未采集
	if((adc_val < 30) && ~pick_ed) {
		pick_ed = 1;
		//采集开始时间
		pick_time = t1_count;
		
		//------->采集温度
		temp = (DS18B20_readTemp()/16.0)*10;
		//数据校验
		if(temp < 0) temp = 0;
		else if(temp > 990) temp = 990;
		//高温报警
		warn_en = (temp > ctrl_temp*10) ? 1 : 0;
		
		//------->采集湿度
		humi_read();
		
		if(humi_ok) {
			//采集次数
			if(pick_num < 99)
				pick_num++;
			//数据计算
			calc_proc();
		}
		
		//------->采集完毕，切换到温湿度界面
		seg_mode_old = seg_mode;
		seg_mode = 'T';
	}

}


//===========LED=============
void led_proc() {
	if(t1_count%50) return;
	
	//时间界面
	if(seg_mode == 0) led_code |= 0x01;
	else led_code &= ~0x01;
	//回显界面
	if(seg_mode == 1) led_code |= 0x02;
	else led_code &= ~0x02;	
	//温湿度界面
	if(seg_mode == 'T') led_code |= 0x04;
	else led_code &= ~0x04;
	
	//湿度无效
	if(~humi_ok) led_code |= 0x10;
	else led_code &= ~0x10;
	
	//采集数据均增
	if(pick_incre) led_code |= 0x20;
	else led_code &= ~0x20;
	
}


//===========SEG=============
void seg_proc() {
	if(t1_count%200) return;
	
	//数据采集
	DS1302_getRTC(RTC);
	task_proc();
	
	switch(seg_mode) {
		case 0://1 时间
			//sprintf(seg_str, "%8d", freq);
			sprintf(seg_str, "%02d-%02d-%02d", (uint)RTC[0], (uint)RTC[1], (uint)RTC[2]);
		break;
		case 1://2 回显
			if(pick_num) {
				if(redsp_mode == 0) {//温度
					sprintf(seg_str, "C %02d-%3.1f", temp_max/10, (float)(temp_avg/10.0));
				}
				else if(redsp_mode == 1) {//湿度
					sprintf(seg_str, "H %02d-%3.1f", humi_max/10, (float)(humi_avg/10.0));
				}
				else {//采集触发、触发时间
					sprintf(seg_str, "F%02d%02d-%02d", (uint)pick_num,
					(uint)pick_RTC[0], (uint)pick_RTC[1]);
				}
			} else {
				if(redsp_mode == 0) {
					sprintf(seg_str, "C       ");
				}
				else if(redsp_mode == 1) {
					sprintf(seg_str, "H       ");
				}
				else {
					sprintf(seg_str, "F%02d     ", (uint)pick_num);
				}
			}
		break;
		case 2://3 参数
			sprintf(seg_str, "P     %02d", (uint)ctrl_temp);
		break;
		case 'T'://4 温湿度
			if(humi_ok)
				sprintf(seg_str, "E  %02d-%02d", temp/10, humi/10);
			else 
				sprintf(seg_str, "E  %02d-AA", temp/10);
		break;
	}
	
	seg_tran(seg_str, seg_buf);
}


//===========KEY=============
void key_proc() {
	static uchar key_val,key_down,key_up;
	static ulong s9_time;
	
	if(t1_count%10) return;
	
	//读取键码
	key_val = key_scan_kbd();
	key_down = key_val & (key_old^key_val);
	key_up = ~key_val & (key_old^key_val);
	key_old = key_val;
	
	//处于温湿度界面时，所有按键无效
	if(seg_mode == 'T') return;
	
	//主界面切换
	if(key_down == 4) {
		if(++seg_mode == 3)
			seg_mode = 0;
		if(seg_mode == 0)
			redsp_mode = 0;
	}
	
	//回显界面切换
	if(key_down == 5 && seg_mode == 1) {
		if(++redsp_mode == 3)
			redsp_mode = 0;
	}
	
	//设置温度参数：温度加
	if(key_down == 8 && seg_mode == 2) {
		if(ctrl_temp < 99)
			ctrl_temp++;
	}
	
	//S9
	if(key_down == 9) { //记录按下时间
		s9_time = t1_count;
	}
	if(key_up == 9) {
		//参数界面，温度减
		if((t1_count-s9_time) < 2000 && seg_mode == 2) {
			if(ctrl_temp > 0) 
				ctrl_temp--;
		} 
		//时间回显界面，长按2s清空采集数据
		else if((t1_count-s9_time) > 2000 && redsp_mode == 2) { 
			clear_data();
		}
	}
	
}


//===========ISR=============
void timer1_init() {
	AUXR &= 0xBF;
	TMOD &= 0x0F;
	TH1 = 0xFC;
	TL1 = 0x18;
	TF1 = 0;
	ET1 = 1;
	TR1 = 1;
	EA = 1;
}

void isr_timer_1() interrupt 3 {
	t1_count++;
	
	//采集555频率
	if(!(t1_count%200)) {
		freq = ne555_read()*5;
	}
	
	//高温报警
	if(warn_en) {
		if(++warn_count == 100) {
			warn_count = 0;
			led_code ^= 0x08;
		}
	} else {
		led_code &= ~0x08;
	}
	
	
	LED(led_code);
	seg_disp(seg_pos, seg_buf);
	if(++seg_pos == 8) seg_pos = 0;
}


//===========MAIN=============
void main() {
	LED(0);
	BUZ(0);
	ne555_init();
	timer1_init();

	DS1302_setRTC(RTC);
	DS18B20_readTemp();
	
	while(1) {	
		led_proc();
		seg_proc();
		key_proc();
	}
}


